package study.io.springboot.upload.controller;

import cn.hutool.core.io.IoUtil;
import cn.hutool.core.io.unit.DataSizeUtil;
import cn.hutool.core.util.IdUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import study.eggs.result.Result;
import study.eggs.result.Results;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;

/**
 * -server -Xms128M -Xmx128M
 */
@Slf4j
@RestController
@RequestMapping("/upload")
public class _1_UploadController {

    int _KB = 1024;

    int _MB = 1024 * _KB;

    /**
     * 流读入内存
     * （1）对应用内存容量要求较高
     */
    @RequestMapping("/read2Memory")
    public Result read2Memory(@RequestParam("file") MultipartFile file) {
        log.info(">>>>>> 文件大小: {}", DataSizeUtil.format(file.getSize()));
        //
        byte[] data;
        try (InputStream is = file.getInputStream()) {
            // 读入内存
            data = IoUtil.readBytes(is);


            // 处理数据

        } catch (Exception ex) {
            throw new RuntimeException("上传文件异常: ", ex);
        } finally {
            // 尽快释放内存？
            data = new byte[0];
        }
        return Results.ok();
    }

    /**
     * 流保存为本地文件
     * （1）流使用完需要关闭，否则跟流关联文件不可删除
     * （2）流不可重复读取，如读取文件魔数
     */
    @RequestMapping("/save2File")
    public Result save2File(@RequestParam("file") MultipartFile file) {
        log.info(">>>>>> 文件大小: {}", DataSizeUtil.format(file.getSize()));
        // 临时文件
        String tempFileId = IdUtil.fastSimpleUUID();
        File tempFile = new File(tempFileId);
        //
        try (InputStream is = file.getInputStream();
             OutputStream out = new FileOutputStream(tempFile)) {
            // 保存为临时文件
            //
            IoUtil.copy(is, out);


            // 处理文件

        } catch (Exception ex) {
            throw new RuntimeException("上传文件异常: ", ex);
        } finally {
            // 清理临时文件
//            FileUtil.del(tempFile);
        }
        return Results.ok();
    }


    /**
     * 多文件读取
     * （1）上传文件异步:  异步阻塞可以，完全异步不可以
     * （2）
     */
    @RequestMapping("/multiFile")
    public Result multiFile(@RequestParam("files") List<MultipartFile> files,
                            @RequestParam(name = "name", required = false) String test) {
        // 文件数量
//        if (CollectionUtil.size(files) > 2) {
//            return Results.fail();
//        }
        // 文件总大小
        Long total = files.stream()
                .mapToLong(MultipartFile::getSize).sum();
        log.info(">>>>>> {}", DataSizeUtil.format(total));

        // 异步处理单文件
//        for (MultipartFile file : files) {
//
//            ThreadUtil.execute(() -> {
//                try {
//                    String oriName = file.getOriginalFilename();
//                    String name = file.getName(); //变量名，files
//                    Long size = file.getSize();
//                    log.info(">>>>>> {}, {}, {}", oriName, name, DataSizeUtil.format(size));
//                    file.transferTo(new File(oriName));
//                } catch (Exception ex) {
//                    ex.printStackTrace();
//                }
//            });
//
//        }
        // 异步阻塞处理单文件
        files.parallelStream().forEach(file -> {
            try {
                String oriName = file.getOriginalFilename();
                Long size = file.getSize();
                log.info(">>>>>> {}, {}", oriName, DataSizeUtil.format(size));
                file.transferTo(new File(oriName));
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        });
        return Results.ok();
    }

    /**
     * 流直接输出
     */
    @RequestMapping("/toOutput")
    public Result toOutput(@RequestParam("file") MultipartFile file) {
        // 根据文件后缀
        log.info("文件类型 {}", file.getContentType());

        //
        try (InputStream is = file.getInputStream()) {

            // byte[] data = IoUtil.readBytes(is);


        } catch (Exception ex) {
            throw new RuntimeException("上传文件异常: ", ex);
        }
        return Results.ok();
    }
}
